
package test;

import java.io.IOException;
import java.rmi.AccessException;
import java.rmi.AlreadyBoundException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;



import node.ActualNode;
import node.Node;
import node.Validator;

/**
 * Just a tester class.
 * @author TCSS 558 Team 6
 * @version Spring 2013
 * 
 */

public final class NodeMain
{

  /* Setting the sleept time.*/
  private static final int SLEEP_TIME = 10000;

  /**
   * 
   * The node.
   */
  private static Node my_node;

  private NodeMain()
  {
    // do nothing
  }
/**
 * 
 * @param the_registry .
 * @throws AccessException
 * @throws RemoteException
 */
  public static void isSettled(final Registry the_registry) throws AccessException,
      RemoteException
  {
    final String[] registered_nodes = the_registry.list();
    if (registered_nodes.length != 0)
    {
      System.out.println("The system has already set up");
      System.exit(1);
    }
  }

  /**
   * The main method for ActualNode. Initializes an actual node with a given
   * Node_ID and an M value and binds it to the registry.
   * 
   * @param the_args An array of Strings containing the command line arguments.
   *          The first argument is the host name, the second is the port
   *          number, the third is the registry name, the fourth is the node id
   *          and the fifth is m value.
   */

  public static void main(final String... the_args)
  {
    // get a reference to the remote registry.
    final String host = the_args[0];
    final int port = Integer.parseInt(the_args[1]);
    final String registry_name = the_args[2];
    
    try
    {
      
      final Registry bootstrap = LocateRegistry.getRegistry(host, port);
      final Registry registry = (Registry) bootstrap.lookup(registry_name);
      // checks if the system is set up.
      isSettled(registry);
      System.out.println("Waiting for other nodes.");
      Thread.sleep(SLEEP_TIME);
      // checks the m value: whether it is a valid integer and it is the same in
      // the system.
      final int m_value = Validator.validate(registry, the_args[4]);

      final String[] registered_nodes = registry.list();
      // prints the list of registered nodes.
      System.out.println("List of registered nodes:");
      for (int i = 0; i < registered_nodes.length; i++)
      {
        System.out.println("Node registered: " + registered_nodes[i]);
      }
      final int node_id = Validator.validateNode(registered_nodes, the_args[3], m_value);

      // binds the node.
      my_node = new ActualNode(node_id, m_value, registry);

      System.out.println("Adding a node id " + node_id + " to the system");
      System.out.println("Binding node " + node_id + " to registry now.");
      registry.bind("node_id_" + node_id, UnicastRemoteObject.exportObject(my_node, 0));
      System.out.println("Node " + node_id + " bound to registry.");

      // waits for other nodes to finish registering
      Thread.sleep(SLEEP_TIME);
      // gets the virtual nodes.
      System.out.println("Initializing the virtual nodes................");
      ((Node) my_node).initialize();

      System.out.println("System initialized.");
      Thread.sleep(SLEEP_TIME);


    }
    catch (final RemoteException e)
    {
      System.err.println("a problem occurred at remote method call." + e);
      System.exit(1);
    }
    catch (final NotBoundException e)
    {
      System.err.println("The object doesn't bind.");
      System.exit(1);
    }
    catch (final IOException e)
    {
      e.printStackTrace();
    }
    catch (final AlreadyBoundException e)
    {
      System.err.println("Node has already bound.");
      System.exit(1);
    }
    catch (final ArrayIndexOutOfBoundsException e)
    {
      System.err.println("Usage:java NodeMain <host> "
                         + "<port> <registry name> <node_id> <m value>");
      e.printStackTrace();
    }
    catch (InterruptedException e)
    {
      
      e.printStackTrace();
    }

  }

}
